grammar Wezlang;


prog : (line | struct_def)+ ;

line : variable ';'
    | if_block 
    | typed_var ';'
    | expr ';'
    ;

block : line* ;

function_call :  NAME '(' ')' 
              | NAME '(' expr_list ')' 
             ;


struct_def : STRUCT TNAME '{' ( typed_var ';' )* '}' ;

type_list : typed_var ',' type_list
          | typed_var 
          ;

typed_var : NAME ':' type ;

type : '(' type ')' 
		 | type ('->'  type)+
		 | TNAME
		 ;
			
/*
type : '(' type ')'
     | type ('->' type)+
     | (NAME | TNAME)+
    ;
*/

variable : NAME '=' expr ;

if_block : IF expr '{' block '}' elif_block ;

elif_block : (ELIF expr '{' block '}')* ELSE '{' block '}'
    | (ELIF expr '{' block '}')* 
    ;


expr : '(' expr ')'
     | primitive
     | NAME
     | function 
     | function_call
     | expr OPER_1 expr
     | expr OPER_2 expr
     | expr OPER_3 expr
     | expr OPER_4 expr
     | OPER_R expr
     ;

expr_list : expr (',' expr)*
          |  
          ;

primitive : INT | FLOAT | STRING  | BOOL ;

function : '(' arg_list ')' '{' line* '}' ;

arg_list : NAME (',' NAME)* 
         |
         ;

FOR : 'for' ;
IF : 'if' ;
ELSE : 'else' ;
ELIF : 'elif' ;
STRUCT : 'struct' ;

BOOL : 'True' | 'False';
 
OPER_1 : [^];
OPER_2 : [*/];
OPER_3 : '+' | '-' | 'or' | 'and' | 'xor' ;
OPER_4 : '%' | '==' ; 
OPER_R : 'not' ;
WS : [\n\r\t ]+ -> skip ;
TNAME : [A-Z][A-Za-z0-9]* ;
NAME : [a-z][A-Za-z0-9]* ;
STRING : '"' [a-zA-Z0-9]* '"' ;
INT : ('-' | )[0-9]+;
FLOAT : ('-' | ) ([0-9]+ '.' [0-9]* | [0-9]* '.' [0-9]+) ;
